#pragma once

#include <mad.h>

#define OUTPUT_BUFFER_SIZE	2048	/* Must be an integer multiple of 4. */
#define MAX_SOFT_MIX_PER_CH	8

class KMp3Stream
{
public:
	u8 *mStreamPtr;
	long mStreamSize;
	bool mIsOk;
	
	explicit KMp3Stream(const char* filename);
	~KMp3Stream();
};



class KMp3Decoder
{
public:
	KMp3Decoder();

    bool	MP3_Play();
    void 	MP3_Pause();
    void 	MP3_Stop();
	
	bool	MP3_Decode(void* buffer, unsigned int numSamples, bool mixPCM);
	
    void 	MP3_Free();
    int 	MP3_Load(const KMp3Stream& stream);
	
    void 	MP3_GetTimeString(char *dest);
    int 	MP3_EndOfStream();

	bool	IsPlaying();
private:
	static signed short MadFixedToSshort(mad_fixed_t Fixed);
	
private:
	const KMp3Stream* mStreamPtr;
	//libmad lowlevel stuff
	// The following variables contain the music data, ie they don't change value until you load a new file
	mad_stream mStream;
	mad_frame mFrame;
	mad_synth mSynth;
	mad_timer_t mTimer;
	// The following varaibles hold the temporary buffer for the decoded audio stream.
	long mSamplesInOutput;
	signed short mOutputBuffer[OUTPUT_BUFFER_SIZE];
	const unsigned char *mOutputBufferEnd;
	unsigned char *mOutputPtr;
	unsigned char *mGuardPtr;
	
	// The following variables will hold current playing status
	int mStatus;
	unsigned long mCurrentFrameIndex;

	// The following variables are maintained and updated by the tracker during playback
	volatile bool mIsPlaying;
	volatile bool mIsPaused;
	int mIsEOS;
};

class KAudioChannel
{
public:
	KAudioChannel(int channel);
	~KAudioChannel();
	
	void PlayStream(const KMp3Stream& stream);
	void TimeElapse(unsigned int ms);
	
private:
	static void AudioCallback(void *_buf2, unsigned int numSamples, void *pdata);
	
private:
	KMp3Decoder mStreamDecoder[MAX_SOFT_MIX_PER_CH];
	int mOccupiedMask[MAX_SOFT_MIX_PER_CH];
	int mChannel;
};
